package com.irdstudio.efp.batch.service.impl.bd;

import com.irdstudio.basic.framework.core.constant.MonAlrmLvlEnums.MonAlrmLvlEnum;
import com.irdstudio.basic.framework.core.util.DateTool;
import com.irdstudio.basic.framework.core.util.ZipUtil;
import com.irdstudio.efp.batch.service.facade.bd.BdDecodeFileService;
import com.irdstudio.efp.batch.service.util.BaiduFileCyptUtil;
import com.irdstudio.efp.loan.service.facade.AccoutErroTempService;
import com.irdstudio.efp.loan.service.vo.AccoutErroTempVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;

/**
 * 需求编号：【2019D1218】（度小满需求）
 * 问题编号：【2019D1218】（解密度小满账务文件）
 * 开发人员：【ludayong】
 * 创建日期：【2020/4/2 17:25】
 * 功能描述：
 * 修改日期：【2020/4/2 17:25】
 * 修改描述：
 */
@Service("bdDecodeFileService")
public class BdDecodeFileServiceImpl implements BdDecodeFileService {

    private static Logger logger = LoggerFactory.getLogger(BdDecodeFileServiceImpl.class);

    @Value("${analysis.accFilePathBaidu}")
    private String accFilePathBaidu;// 同步文件解析路径

    @Value("${baiduFile.tarGz}")
    private String tarGz;// .tar.gz 文件后缀名

    @Value("${baiduFile.md5}")
    private String md5;// md5 文件后缀名

    // 账务文件下载文件名称
    @Value("${baiduFile.baiduAccFileName}")
    private String baiduAccFileName;

    // 账务文件后缀名
    @Value("${baiduFile.baiduFileSuffix}")
    private String baiduFileSuffix;

    // 账务文件解密文件后缀名
    @Value("${baiduFile.baiduAccFileSuffix}")
    private String baiduAccFileSuffix;

    // 对方公钥
    @Value("${baiduFile.getPublicKeyPartner}")
    private String getPublicKeyPartner;

    // 我方私钥
    @Value("${baiduFile.getPrivateKeyLocal}")
    private String getPrivateKeyLocal;

    // 同步文件记录异常信息
    @Autowired
    @Qualifier("accoutErroTempService")
    private AccoutErroTempService accoutErroTempService;

    // 正式业务
    private static final String TYPE_LF = "LF";

    // 解密存放文件夹
    @Value("${baiduFile.baiduJm}")
    private String baiduJm;

    // 解压文件夹
    @Value("${baiduFile.baiduJy}")
    private String baiduJy;


    /**
     * 需求编号：【2019D1218】（度小满需求）
     * 问题编号：【2019D1218】（解密度小满账务文件）
     * 开发人员：【ludayong】
     * 创建日期：【2020/4/2 17:25】
     * 功能描述：
     * 修改日期：【2020/4/2 17:25】
     * 修改描述：
     */
    @Override
    public boolean decryptFile(String curDate, String prdCode, String fileType, String type) {
        boolean result = false;
        try {
            String filePath = accFilePathBaidu + prdCode + File.separator + curDate;
            // 文件类型：账务文件
            String fileName = baiduAccFileName.replace("curDate", curDate);
            // 解密文件名称
            String baiduJmFileName = baiduAccFileSuffix.replace("curDate", curDate);
            // 文件名称(无后缀)
            String localFileMd5 = filePath + File.separator + type + File.separator + fileName + md5;
            // 具体到文件名
            String localFileTar = filePath + File.separator + type + File.separator + fileName + tarGz;

            // 清理度小满账务文件
            clearAccFile(filePath);

            File localFileTarFe = new File(localFileTar);
            if (!localFileTarFe.exists()) {
                String remark = "文件不存在：" + localFileTarFe;
                String tableName = "bd_acc_ledger";
                addErrorInfo(tableName, MonAlrmLvlEnum.SERIOUS.getEnname(), remark, remark);
                logger.error(remark);
                return result;
            }

            // 度小满账务文件解密
            BaiduFileCyptUtil.decryptFile(new File(localFileTar), new File(localFileMd5), filePath + File.separator, baiduJmFileName,
                    getPrivateKeyLocal, getPublicKeyPartner);

            // 清理度小满解密账务文件
            clearAccFile(filePath + File.separator + type + File.separator);
            result =  true;
        } catch (Exception e) {
            result = false;
            String errorMsg = "解密度小满账务文件出错！";
            String remark = "解密度小满账务文件出错，错误信息：" + e.getMessage();
            String tableName = "bd_acc_ledger";
            addErrorInfo(tableName, MonAlrmLvlEnum.SERIOUS.getEnname(), errorMsg, remark);
            logger.error(remark);
        }
        return result;
    }

    /**
     * 需求编号：【2019D1218】（度小满需求）
     * 问题编号：【2019D1218】（度小满账务文件清理）
     * 开发人员：【ludayong】
     * 创建日期：【2020/4/2 19:18】
     * 功能描述：
     * 修改日期：【2020/4/2 19:18】
     * 修改描述：
     */
    public void clearAccFile(String filePath) {
        // 账务文件路径
        logger.info("度小满账务文件清理路径：" + filePath);
        // 账务文件路径
        File files = new File(filePath);
        // 同步文件解析路径
        if (files.exists()) {
            File[] accFiles = files.listFiles();
            if (accFiles.length > 0) {
                for (File accFile : accFiles) {
                    if (accFile.isFile()) {
                        if (accFile.getName().endsWith(baiduFileSuffix) || "key".equals(accFile.getName())) {
                            boolean removeFileRes = ZipUtil.deleteFile(accFile.getAbsolutePath());
                            logger.info("度小满账务文件清理:" + accFile.getAbsolutePath() + "结果[" + removeFileRes + "]");
                        }
                    }
                }
            }
        }
    }

    /**
     * 需求编号：【2019D1218】（度小满需求）
     * 问题编号：【2019D1218】（记录异常信息）
     * 开发人员：【ludayong】
     * 创建日期：【2020/4/2 19:18】
     * 功能描述：
     * 修改日期：【2020/4/2 19:18】
     * 修改描述：
     */
    private void addErrorInfo(String tableName, String errorType, String errorMsg, String remark) {
        AccoutErroTempVO accoutErroTempVO = new AccoutErroTempVO();
        // 表名
        accoutErroTempVO.setTableName(tableName);
        // 错误级别
        accoutErroTempVO.setErroType(errorType);
        // 错误信息
        accoutErroTempVO.setErroMsg(errorMsg);
        // 备注
        accoutErroTempVO.setRemark(remark);
        // 创建时间
        accoutErroTempVO.setCreateData(DateTool.getCurrentDateTime());
        // 修改时间
        accoutErroTempVO.setLastModifyTime(DateTool.getCurrentDateTime());
        // 记录异常信息
        accoutErroTempService.insert(accoutErroTempVO);
    }
}
